package com.college.common.utils.security;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;


/**
 * 拍拍贷aes解密工具类
 */
@Slf4j
public class PPDAesUtils {

    /**
     * 加密模式之 ECB，算法/模式/补码方式
     */
    private static final String AES_ECB = "AES/ECB/PKCS5PADDING";

    /**
     * 加密模式之 CBC，算法/模式/补码方式
     */
    private static final String AES_CBC = "AES/CBC/PKCS5PADDING";

    /**
     * 加密模式之 CFB，算法/模式/补码方式
     */
    private static final String AES_CFB = "AES/CFB/PKCS5PADDING";

    /**
     * 小安分期Des加密Key
     */
    public static final String KEY = "_@Ks`Y*9jLb.hvho}C;GwDpw";

    /**
     * 企惠通Des加密key
     */
    public static final String QHT_KEY = "aS7^sH1.gO8>nA4!mK7+aP0_";

    /**
     * 小安分期Des向量Iv
     */
    public static final String IV = "2%8iTpSi";
    /**
     * 字符编码
     */
    public static final String DEFAULT_ENC_NAME = "UTF-8";

    /**
     * @param content   加密内容
     * @param secretKey 加密秘钥
     * @return
     * @throws Exception 错误信息
     */
    public static String encrypt(String content, String secretKey) {
        try {
            // 填充算法加密模式
            Cipher cipher = Cipher.getInstance(AES_CBC);
            // 填充加密秘钥
            SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES");
            // 创建iv初始化向量
            IvParameterSpec iv = new IvParameterSpec(secretKey.getBytes(StandardCharsets.UTF_8));
            // 初始化密码器（加密模型）
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
            // 加密数据，返回密文
            byte[] encrypted = cipher.doFinal(content.getBytes());
            // 将密文转为Base64二次加密
            return new Base64().encodeToString(encrypted);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Aes解密
     *
     * @param content   解密内容
     * @param secretKey 解密秘钥
     * @return
     */
    public static String decrypt(String content, String secretKey) {

        try {
            // 创建秘钥对象
            SecretKeySpec skeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES");
            // 创建iv初始化向量对象
            IvParameterSpec iv = new IvParameterSpec(secretKey.getBytes(StandardCharsets.UTF_8));
            // 填充加密模型
            Cipher cipher = Cipher.getInstance(AES_CBC);
            // 初始化密码器（加密模型）
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            // 解密数据，返回解密铭文
            byte[] original = cipher.doFinal(Base64.decodeBase64(content));
            // 转为字符串
            return new String(original);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Des加密
     *
     * @param data
     * @return
     */
    public static String java_openssl_encrypt(String data) {
        return java_openssl_encrypt(data, IV);
    }

    /**
     * java_openssl_encrypt加密算法
     *
     * @param data
     * @param iv
     * @return
     * @throws Exception
     */
    public static String java_openssl_encrypt(String data, String iv) {
        try {
            Cipher cipher = createCipher(iv, Cipher.ENCRYPT_MODE);
            return URLEncoder.encode(java.util.Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes())), DEFAULT_ENC_NAME);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println("加密="+ java_openssl_encrypt("{\"phone\":\"18300005544\",\"channelSign\":\"123\"}"));
        String name  = java_openssl_encrypt("{\"phone\":\"18300005544\",\"channelSign\":\"123\"}");
        System.out.println("解密="+java_openssl_decrypt_qht(name));
//        System.out.println(java_openssl_encrypt("{\"phone\":\"18300005544\",\"channelSign\":\"123\"}",IV));
    }

    /**
     * Des解密
     *
     * @param data
     * @return
     */
    public static String java_openssl_decrypt(String data) {
        return java_openssl_decrypt(data, IV);
    }

    /**
     * Des解密 企惠通
     *
     * @param data
     * @return
     */
    public static String java_openssl_decrypt_qht(String data) {

        try {
            Cipher cipher = createCipherQht(IV, Cipher.DECRYPT_MODE);
            return new String(cipher.doFinal(java.util.Base64.getDecoder().decode(URLDecoder.decode(data, DEFAULT_ENC_NAME))));
        } catch (NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException | UnsupportedEncodingException | InvalidAlgorithmParameterException | NoSuchPaddingException | InvalidKeyException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * java_openssl_decrypt解密
     *
     * @param data
     * @param iv
     * @return
     */
    public static String java_openssl_decrypt(String data, String iv) {
        try {
            Cipher cipher = createCipher(iv, Cipher.DECRYPT_MODE);
            return new String(cipher.doFinal(java.util.Base64.getDecoder().decode(URLDecoder.decode(data, DEFAULT_ENC_NAME))));
        } catch (NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException | UnsupportedEncodingException | InvalidAlgorithmParameterException | NoSuchPaddingException | InvalidKeyException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 创建密码器Cipher
     *
     * @param iv
     * @param mode 加/解密模式
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws InvalidAlgorithmParameterException
     */
    private static Cipher createCipher(String iv, int mode) throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, InvalidAlgorithmParameterException {
        byte[] key = KEY.getBytes();
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
        cipher.init(mode, new SecretKeySpec(key, "DESede"), ivParameterSpec);
        return cipher;
    }

    /**
     * 创建密码器Cipher
     *
     * @param iv
     * @param mode 加/解密模式
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws InvalidAlgorithmParameterException
     */
    private static Cipher createCipherQht(String iv, int mode) throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, InvalidAlgorithmParameterException {
        byte[] key = QHT_KEY.getBytes();
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
        cipher.init(mode, new SecretKeySpec(key, "DESede"), ivParameterSpec);
        return cipher;
    }



}